import { BaseView, regView } from '../../../extensions/cocos-scaffold-3x/assets/ui/base/BaseView';
import { _decorator, AssetManager, Component, debug, instantiate, Label, Node, profiler, tween, UITransform, Vec3 } from 'cc';
import { JokerStorage, JC } from './m/JokerStorage';
import { gg } from '../../Game';
import { GameStorage } from '../../../extensions/cocos-scaffold-3x/assets/GameStorage';
import { JCComponent } from './JCComponent';
import { PokerCard, PokerCardProp } from './v/PokerCard';

import { delay, setNodePosY } from '../../../extensions/cocos-scaffold-3x/assets/common/Utils';
import { CardDeckPanel } from './v/CardDeckPanel';
import { ViewJokerLose, ViewJokerLoseProp } from './v/loseGame/ViewJokerLose';
import { ViewFinishJokerStage, ViewFinishJokerStageProp } from './v/finishJokerStage/ViewFinishJokerStage';
import { ViewHandRankBook, ViewHandRankBookProp } from './v/handRankBook/ViewHandRankBook';
import { HandCardPanel } from './v/HandCardPanel';
import { PokerDesk } from './v/PokerDesk';
import { StageInfoPanel } from './v/StageInfoPanel';
import { showToast } from '../../common/Toast';
const { ccclass, property } = _decorator;

@regView({
    bundle: "subBundle",
    prefabPath: "joker/ViewJoker"
}) @ccclass('ViewJoker')
export class ViewJoker extends BaseView {

    @property(HandCardPanel)
    handCardPanel: HandCardPanel = null

    @property(PokerDesk)
    pockerDesk: PokerDesk = null

    @property(StageInfoPanel)
    stageInfoPanel: StageInfoPanel = null


    @property(CardDeckPanel)
    cardDeckPanel: CardDeckPanel = null

    @property(Label)
    lbHandRankTip: Label = null

    @property(Label)
    lbLeftPlayTimes: Label = null

    @property(Label)
    lbLeftDropTimes: Label = null

    jokerStorage: JokerStorage
    pokerGame: JC.PokerGame


    onOpen() {
        profiler.hideStats()
        //@ts-ignore
        this.node.getComponentsInChildren(JCComponent).forEach(
            i => i.init(this)
        )
        this.jokerStorage = gg.storage(JokerStorage)
        this.startNew()
    }

    startNew() {
        this.handCardPanel.clearCards()
        this.pokerGame = new JC.PokerGame()
        this.pokerGame.makeNew()
        this.pokerGame.startNextStage()
        this.drawCards()
        this.refreshOrderDesc()

    }

    waittingCount = 0

    isNumOrder = true

    @property(Label)
    lbOrder: Label = null
    onTouchChangeOrder() {
        this.isNumOrder = !this.isNumOrder
        this.refreshOrderDesc()

        this.refreshHandCardsOrder()
    }

    refreshOrderDesc() {
        this.lbOrder.string = this.isNumOrder ? "按花色\n排序" : "按大小\n排序"
    }


    async drawCards() {
        const newCards = this.pokerGame.drawCards()

        newCards.forEach((card, index) => {
            let node = instantiate(this.handCardPanel.cardPrefab)
            node.getComponent(PokerCard).init(new PokerCardProp(card, this))
            node.parent = this.node
            node.setPosition(this.cardDeckPanel.node.position)

            tween(node)
                .delay(index * 0.1)
                .to(0.3, { position: this.handCardPanel.node.position })
                .call(() => {
                    node.parent = this.handCardPanel.layout.node
                    setNodePosY(node, 0)
                    this.refreshHandCardsOrder()

                })
                .start()


        })
        await delay(newCards.length * 0.1 + 0.5)

    }

    refreshHandCardsOrder() {
        if (this.isNumOrder) {
            const cards = this.handCardPanel.layout.node.children.slice().sort((a, b) => {
                return b.getComponent(PokerCard).prop.card.point - a.getComponent(PokerCard).prop.card.point
            })
            cards.forEach((node, index) => {
                node.setSiblingIndex(index)
            })
        } else {
            const cards = this.handCardPanel.layout.node.children.slice().sort((a, b) => {
                return a.getComponent(PokerCard).prop.card.suit - b.getComponent(PokerCard).prop.card.suit
            })
            cards.forEach((node, index) => {
                node.setSiblingIndex(index)
            })
        }
    }

    async playCardsAddScore(cards: PokerCard[], playInfo: {
        rankType: JC.EHandRank;
        handRankCards: JC.PokerCard[];
        handRank: JC.HandRank

    }) {
        this.waittingCount++
        this.pokerGame.currentStage.base = playInfo.handRank.getBase()
        this.pokerGame.currentStage.mul = playInfo.handRank.getMul()

        this.lbHandRankTip.string = `${JC.EHandRankNameMap[playInfo.handRank.type]}`
        tween(this.lbHandRankTip.node).to(0.3, { scale: new Vec3(1, 1, 1) }, { easing: "expoOut" }).delay(0.5).to(0.3, { scale: new Vec3(0, 0, 0) }, { easing: "expoOut" }).start()

        await delay(1000)

        for (let index = 0; index < cards.length; index++) {
            const card = cards[index];
            if (playInfo.handRankCards.find(i => i.id == card.prop.card.id)) {
                await card.playAddScore()
            }

        }

        this.scheduleOnce(() => {
            this.pokerGame.currentStage.addScore(this.pokerGame.currentStage.base * this.pokerGame.currentStage.mul)
        }, 1)


        this.scheduleOnce(() => {
            if (this.pokerGame.leftPlayTimes <= 0 && this.pokerGame.currentStage.score < this.pokerGame.currentStage.targetNum) {
                gg.openView(ViewJokerLose, { prop: new ViewJokerLoseProp(this, this.pokerGame.currentStage) })
            } else if (this.pokerGame.currentStage.score >= this.pokerGame.currentStage.targetNum) {
                gg.openView(ViewFinishJokerStage, { prop: new ViewFinishJokerStageProp(this, this.pokerGame.currentStage) })
            } else {
                this.drawCards()
                this.pokerGame.currentStage.base = 0
                this.pokerGame.currentStage.mul = 0
            }
            this.waittingCount--

            this.pockerDesk.layout.node.destroyAllChildren()
        }, 2)
    }

    onTouchPlayCard() {
        const cards = this.handCardPanel.getSelectedCards()
        if (!cards.length) {
            return
        }
        const playInfo = this.pokerGame.playCards(cards.map(i => i.prop.card))


        cards.forEach((card, index) => {
            card.node.parent = this.node;
            setNodePosY(card.node, this.handCardPanel.node.position.y)
            this.pokerGame.usedPokerCards.push(card.prop.card)

            tween(card.node)
                .delay(index * 0.1)
                .to(0.3, { position: this.pockerDesk.node.position })
                .call(() => {
                    this.pockerDesk.layout.node.addChild(card.node)
                    setNodePosY(card.node, 0)
                })
                .start()
        })

        this.scheduleOnce(() => {
            this.playCardsAddScore(cards, playInfo)
        }, cards.length * 0.1 + 0.5)


    }

    onTouchDropCard() {
        if (this.pokerGame.leftDropTimes <= 0) {
            showToast("剩余次数不足")
            return
        }
        const cards = this.handCardPanel.getSelectedCards()
        if (!cards.length) {
            return
        }
        this.pokerGame.dropCards(cards.map(i => i.prop.card))


        cards.forEach((card, index) => {
            card.node.parent = this.node;
            setNodePosY(card.node, this.handCardPanel.node.position.y)
            this.waittingCount++
            tween(card.node)
                .delay(index * 0.1)
                .to(0.2, { position: new Vec3(500, card.node.position.y - 200, card.node.position.z) })
                .call(() => {
                    this.pockerDesk.layout.node.addChild(card.node)
                    card.node.destroy()
                    this.waittingCount--
                })
                .start()
        })

        this.scheduleOnce(() => {
            this.drawCards()

        }, 0.1 * cards.length + 0.2)


    }

    /**点击查看牌型图鉴 */
    onTouchHandRankBook() {
        gg.openView(ViewHandRankBook, { prop: new ViewHandRankBookProp(this) })
    }


    startNextStage() {
        this.handCardPanel.clearCards()
        this.pokerGame.startNextStage()
        this.drawCards()

    }

    start() {
    }

    update(deltaTime: number) {
        this.lbLeftPlayTimes.string = `出牌\n(剩${this.pokerGame.leftPlayTimes}次)`
        this.lbLeftDropTimes.string = `弃牌\n(剩${this.pokerGame.leftDropTimes}次)`
    }

    protected onDestroy(): void {
        this.unscheduleAllCallbacks()
    }
}
